Memleak还可以用来验证应用程序中的内存管理是否运转正常,例如"从联系人列表中移除了所有Contact
对象后,系统中已经就不存在Contact
对象了"。Memleak可以交互式运行,在查找内存泄漏时非常有用,对于交互式应用程序来说更是如此,免除了将堆转储到本地文件的麻烦。只要小心仔细些,在辅以相应的系统知识,排查内存泄漏问题就会轻松愉快些了。
假设现在有一个地址簿应用程序,主类是AddressBook
,其中包含了几个内部类,例如用于表示联系人的AddressBook$Contact
类。可以对地址簿执行添加/删除联系人的操作。现在,来验证一下该应用程序中AddressBook$Contact
类的实例是否存在内存泄漏。
正常情况下,Memleak只会显示那些堆内存使用率达到0.1%以上的类型,和创建实例过多的类型。对于那些不会引发内存泄漏的类型,不必太关心,随着应用程序的不断运行,有问题的类会占用越来越多的堆内存。但是,很多时候,被泄漏的内存只会占用一小部分内存,等到应用程序运行了相当一段时间后,才会变得明显起来。为了更好的检测内存泄漏,可以将内存占用率阈值设为0,如下图所示:
然后过滤出那些想要测试的类,观察其在应用程序中的行为变化。
在第7章中曾经介绍过,JRockit Mission Control中的过滤框可以通过添加
regexp
前缀来输入正则表达式。
在下面的截图中可以看到,从AddressBook
中移除了3个地址,但Contact
实例的数量却没有发生变化:
移除对象后,AddressBook$Contact
实例的数量却没有变化,说明确实发生了内存泄漏。
若希望Memleak能及时显示出堆内存的变化,可以将趋势表的刷新间隔调低。
由于所有的Contact
实例都没有被回收掉,因此追踪其中任意一个就可以了。在趋势表中,右键单击Contact
类型,选择 List菜单,将任意实例添加到 Instance Graph,展开其引用路径,然后就可以看到一个名为numberToContact
的Map
实例中。该应用程序的开发人员应该熟悉这种数据结构,找出在哪里使用了它,然后解决之就行了。
内存泄漏的交互式测试主要包括以下几点: